


@[TOC](go语法基础文档)

简介
[语言数据类型](http://www.runoob.com/go/go-data-types.html "语言数据类型")


## 一：变量和作用域
### 1.变量声明 

1.第一种，指定变量类型，声明后若不赋值，使用默认值

```go
/* 单个变量声明 */
var v_name v_type
    v_name = value

    // 示例
    var a int
    a = 10


/* 类型相同多个变量声明 （非全局变量）*/
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3

    // 示例
    var a, b int
    var c string
    a, b, c = 5, 7, "abc"
```

2.根据值自行判定变量类型

```go
/* 单个变量声明 */
var v_name = value

    // 示例
    var a = 18
    var b = false


/* 多个变量声明，自动判断类型 */
var vname1, vname2, vname3 = v1, v2, v3

    // 示例
    var a, b, c = 5, 7, "abc"
```

3.省略var, 注意 :=左侧的变量不应该是已经声明过的，否则会导致编译错误

```go
/* 单个变量声明 */
v_name := value

    // 示例
    a := 19


/* 多个变量声明，自动判断类型 */
vname1, vname2, vname3 := v1, v2, v3 

    // 示例
    a,b,c := 19,false,"string"
```


### 2.并行 或 同时 赋值(两个变量的类型必须是相同)
```go
a := 5
b := 7

// 并行计算
a, b = b, a
fmt.Println("a=", a, " b=", b)

// 结果
// a= 7  b= 5

```
### 3.空白标识符(抛弃值)  _

```go
// 值 5 被抛弃
_, b = 5, 7

//不适用 err 则可以写为 vval,_ = func1()
val, err = Func1(var1)。
```

## 二：常量

声明：
```go
const identifier [type] = value
```

### 1.显示定义
```go
 const b string = "abc"
```

### 2.隐式类型定义
```go
 const b = "abc"
```

### 3.多个常量的声明
```go
const c_name1, c_name2 = value1, value2

// 示例
const a,b = 1,"string"
fmt.Println("a=", a, " b=", b)
```

### 4.枚举
```go
const (
    Unknown = 0
    Female = 1
    Male = 2
)
```

### 5.常量函数表达式 （函数必须是内置函数： len(), cap(), unsafe.Sizeof() ）
```go
const (
    a = "abc"
    b = len(a)
    c = unsafe.Sizeof(a)
)
fmt.Println(a, b, c)
// 结果： abc 3 16
```

### 6.iota 特殊常量，可以认为是一个可以被编译器修改的常量。
```go
const (
    a = iota
    b = iota
    c = iota
)
fmt.Println(a, b, c)
// 结果 0 1 2

const (
    a = iota
    b
    c
)
fmt.Println(a, b, c)
// 结果 0 1 2


const (
    a = iota       // 0
    b = 18         // 独立值 iota += 1
    c = "一个string" // 独立值 iota += 1
    d              // "一个string"
    e              // "一个string"
    f = iota       //恢复计数 iota += 1
    g              // iota += 1
)
fmt.Println(a, b, c, d, e, f, g)
// 结果： 0 18 一个string 一个string 一个string 5 6


/* 左移 << 表示左移 */
const (
    a = 1 << iota
    b = 3 << iota
    c
    d
)
fmt.Println(a, b, c, d)
// 结果：  1 6 12 24
```

---

## 三：运算符

[参考文档](http://www.runoob.com/go/go-operators.html)

---

## 四：条件语句

### 1.if 语句
```go
if 布尔表达式 {
} else if 布尔表达式 {
} else {
}

// 示例
var a int = 10
if a < 20 {
    fmt.Printf("a 小于 20\n" )
}
```

### 2.switch 语句
#### switch
```go
switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}

// 示例
var a int = 10
switch a {
case 1: // a == 1

case 10: // a == 20

default: // 默认值

}
```

#### Type Switch：判断某个 interface 变量中实际存储的变量类型
```go
switch x.(type){
    case type:
       statement(s);      
    case type:
       statement(s); 
    /* 你可以定义任意个数的case */
    default: /* 可选 */
       statement(s);
}

// 示例
var x interface{}
switch i := x.(type) {
   case nil:      
      fmt.Printf(" x 的类型 :%T",i)                
   case int:      
      fmt.Printf("x 是 int 型")                       
   case float64:
      fmt.Printf("x 是 float64 型")           
   case func(int) float64:
      fmt.Printf("x 是 func(int) 型")                      
   case bool, string:
      fmt.Printf("x 是 bool 或 string 型" )       
   default:
      fmt.Printf("未知型")     
}  
```

### 3.select 语句
[参考文档](http://www.runoob.com/go/go-select-statement.html)

```go
select {
    case communication clause  :
       statement(s);      
    case communication clause  :
       statement(s); 
    /* 你可以定义任意数量的 case */
    default : /* 可选 */
       statement(s);
}

// 示例
var c1, c2, c3 chan int
var i1, i2 int
select {
case i1 = <-c1:
    fmt.Printf("received ", i1, " from c1\n")
case c2 <- i2:
    fmt.Printf("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
    if ok {
        fmt.Printf("received ", i3, " from c3\n")
    } else {
        fmt.Printf("c3 is closed\n")
    }
default:
    fmt.Printf("no communication\n")
}
```


---

## 五：循环语句
### 1.for init; condition; post { }
```go
// 示例
for a := 0; a < 3; a++ {
    fmt.Println(a)
}
// 结果 0 1 2
```

### 2.for condition { }
```go
// 示例 1
var a, b int = 0, 3
for a < b {
    a++
    fmt.Println(a)
}
// 结果 1 2 3

// 示例2：无限循环
var i int = 0
for true {
    i++
}
```
### 3.for { }  
> 备注：for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环
```go
// 示例
var list = [3]int{1, 2, 3}
for key, value := range list {
    fmt.Println("key=", key, "value=", value)
}

/*
结果
key= 0 value= 1
key= 1 value= 2
key= 2 value= 3
*/
```
### 4.循环控制语句
- break 语句  经常用于中断当前 for 循环或跳出 switch 语句
- continue 语句   跳过当前循环的剩余语句，然后继续进行下一轮循环。
- goto 语句   将控制转移到被标记的语句。 [参考连接](http://www.runoob.com/go/go-goto-statement.html)
```go
  /* 定义局部变量 */
  var a int = 10

  /* 循环 */
  LOOP: for a < 20 {
     if a == 15 {
        /* 跳过迭代 */
        a = a + 1
        goto LOOP
     }
     fmt.Printf("a的值为 : %d\n", a)
     a++     
  } 
```


---

## 六：函数
主函数：**main  函数 必须存在**
```go
func main() {
}
```

声明：
```go
func 函数名( [函数参数...] ) [返回类型] {
    函数体
}
```
### 1.函数参数
#### 1.值传递
```go
// 示例1：
max(1,30)
func max(num1, num2 int) int {
    /* 定义局部变量 */
    var result int
    if (num1 > num2) {
        result = num1
    } else {
        result = num2
    }
    return result
}

// 示例2：多类型接收与多类型声明返回
func function(a []int, b int, c bool, d map[int][]int) (list []int, data int, err error) {
    return
}

// 示例3：多类型接收与多类型返回
func function(a []int, b int, c bool, d map[int][]int) ([]int, int, error) {
    // 未声明变量，需要函数里声明，return 返回具体的变量
    var list = []int{}
    var data int
    var err error

    return list, data, err
}
```
#### 2.引用传递
```go
/* 定义局部变量 */
func man{
    var a int = 100
    var b int= 200

    fmt.Printf("交换前，a 的值 : %d\n", a )
    fmt.Printf("交换前，b 的值 : %d\n", b )

    /* 调用 swap() 函数
    * &a 指向 a 指针，a 变量的地址
    * &b 指向 b 指针，b 变量的地址
    */
    swap(&a, &b)

    fmt.Printf("交换后，a 的值 : %d\n", a )
    fmt.Printf("交换后，b 的值 : %d\n", b )
}
func swap(x *int, y *int) {
    var temp int
    temp = *x    /* 保存 x 地址上的值 */
    *x = *y      /* 将 y 值赋给 x */
    *y = temp    /* 将 temp 值赋给 y */
}
/*
执行结果:
交换前，a 的值 : 100
交换前，b 的值 : 200
交换后，a 的值 : 200
交换后，b 的值 : 100
*/
```

### 2.函数用法

#### 1.函数作为值
```go
/* 声明函数变量 */
getSquareRoot := func(x float64) float64 {
    // 开平方根
    return math.Sqrt(x)
}
/* 使用函数 */
fmt.Println(getSquareRoot(9))
```

#### 2.闭包
> 匿名函数是一个"内联"语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量，不必申明。
```go
func main{
    /* nextNumber 为一个函数，函数 i 为 0 */
    nextNumber := getSequence()

    /* 调用 nextNumber 函数，i 变量自增 1 并返回 */
    fmt.Println(nextNumber())
    fmt.Println(nextNumber())
    fmt.Println(nextNumber())

    /* 创建新的函数 nextNumber1，并查看结果 */
    nextNumber1 := getSequence()
    fmt.Println(nextNumber1())
    fmt.Println(nextNumber1())
}
func getSequence() func() int {
    i := 0
    return func() int {
        i += 1
        return i
    }
}
```

#### 3.函数方法（类）
```go
/* 定义结构体 */
type Circle struct {
  radius float64
}
func main() {
  var c1 Circle
  c1.radius = 10.00
  fmt.Println("圆的面积 = ", c1.getArea())
}
//该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
  //c.radius 即为 Circle 类型对象中的属性
  return 3.14 * c.radius * c.radius
}
```

---

## 七：数组
声明：
```go
var variable_name [SIZE] variable_type
```
### 初始化数组

#### 1.固定长度数组
备注：
- [] 设定数组个数
- {} 是数组元素
- 数组中 {} 中的元素个数不能大于 [] 中的数字

```go
var a [10]int
var b [10] int
var c = []int{1, 2, 3, 4, 5, 6}
```

#### 2.无限长度数组
备注：
- 忽略 [] 中的数字不设置数组大小，根据元素的个数来设置数组的大小

```go
var a []int
var b [] int
var c = []int{1, 2, 3, 4, 5, 6}
```

### 访问数组元素
备注：
- 数组元素可以通过索引（位置）来读取（或者修改），索引从0开始，第一个元素索引为 0，第二个索引为 1，以此类推

#### 1.一维数组
```go
var n [3]int /* n 是一个长度为 3 的数组 */
fmt.Println(len(n))

var length = len(n) // 数组的长度为3

/* 为数组 n 初始化元素 */
for i := 0; i < length; i++ {
  n[i] = i + 100 /* 设置元素为 i + 100 */
}

/* 数组元素读取 */
for i := 0; i < length; i++ {
  fmt.Println(i, n[i])
}
/*
执行结果：
3
0 100
1 101
2 102
*/
```
```go

```

#### 2.多维数组
```go
var threedim [3][4][5]int
fmt.Println(threedim)
/*
执行结果：
[
    [
        [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]
    ] 
    [
        [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]
    ] 
    [
        [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]
    ]
]
*/

// 赋值
array[0][1][1] = 10
// 读取
fmt.Println(array[0][1][1])
```
#### 3.函数传递数组
1.方式一：形参设定数组大小
```go
void myFunction(param [10]int)
{
}
```

2.方式二：形参未设定数组大小
```go
void myFunction(param []int)
{
}
```
示例：
```go
func function(arr []int, data [5]int) {

}
```

## 八：指针
指针：一个指针变量指向了一个值的内存地址
声明：
```go
var var_name *var-type
```
var-type 为指针类型，var_name 为指针变量名，* 号用于指定变量是作为一个指针
```go
var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */
```
### 1.指针使用
- 定义指针变量。
- 为指针变量赋值。
- 访问指针变量中指向地址的值。
```go
  // 定义指针变量
  var a int = 20
  var b *int

  // 赋值
  b = &a /* 指针变量的存储地址 */
  
  fmt.Printf("a 变量的地址是: %x\n", &a)

  /* 指针变量的存储地址 */
  fmt.Printf("b 变量储存的指针地址: %x\n", b)

  /* 使用指针访问值 */
  fmt.Printf("*b 变量的值: %d\n", *b)
```

### 2.空指针
当一个指针被定义后没有分配到任何变量时，它的值为 nil，nil 指针也称为空指针
```go
var ptr *int

fmt.Printf("ptr 的值为 : %x\n", ptr)

if (ptr == nil) {
  fmt.Println("ptr = nil")
}
/*
执行结果：
ptr 的值为 : 0
ptr = nil
*/
```

### 3.指针数组
```go
a := []int{10, 100, 200}
var i int
var ptr [3]*int;
for i = 0; i < 3; i++ {
  ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
}
for i = 0; i < 3; i++ {
  fmt.Printf("a[%d] = %d\n", i, *ptr[i])
}
```

### 4.指向指针的指针
如果一个指针变量存放的又是另一个指针变量的地址，则称这个指针变量为指向指针的指针变量
声明：
```go
var ptr **int;
```
访问指向指针的指针变量值需要使用两个 * 号
```go
var a int
var ptr *int
var pptr **int

a = 3000

/* 指针 ptr 地址 */
ptr = &a

/* 指向指针 ptr 地址 */
pptr = &ptr

/* 获取 pptr 的值 */
fmt.Printf("变量 a = %d\n", a)
fmt.Printf("指针变量 *ptr = %d\n", *ptr)
fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
/*
执行结果：
变量 a = 3000
指针变量 *ptr = 3000
指向指针的指针变量 **pptr = 3000
*/
```

### 5.向函数传递指针参数
```go
import "fmt"

func main() {
   /* 定义局部变量 */
   var a int = 100
   var b int= 200

   fmt.Printf("交换前 a 的值 : %d\n", a )
   fmt.Printf("交换前 b 的值 : %d\n", b )

   /* 调用函数用于交换值
   * &a 指向 a 变量的地址
   * &b 指向 b 变量的地址
   */
   swap(&a, &b);

   fmt.Printf("交换后 a 的值 : %d\n", a )
   fmt.Printf("交换后 b 的值 : %d\n", b )
}

func swap(x *int, y *int) {
   var temp int
   temp = *x    /* 保存 x 地址的值 */
   *x = *y      /* 将 y 赋值给 x */
   *y = temp    /* 将 temp 赋值给 y */
}
```

## 九：结构体
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合

### 1.定义结构体
结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型，结构体有中有一个或多个成员。type 语句设定了结构体的名称。
```go
type struct_variable_type struct {
   member definition;
   member definition;
   ...
   member definition;
}
```
变量的声明
```go
// 普通索引形式
variable_name := structure_variable_type {value1, value2...valuen}
//  key => value 结构形式
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
```

```go
package main
import "fmt"
type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
    // 创建一个新的结构体
    fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
    // 也可以使用 key => value 格式
    fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
    // 忽略的字段为 0 或 空
   fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
```

### 2.访问结构体成员
```go
type Books struct {
  title string
  author string
  subject string
  book_id int
}
func main() {
  var Book1 Books        /* 声明 Book1 为 Books 类型 */
  var Book2 Books        /* 声明 Book2 为 Books 类型 */
  
  /* book 1 描述 */
  Book1.title = "Go 语言"
  Book1.author = "www.runoob.com"
  Book1.subject = "Go 语言教程"
  Book1.book_id = 6495407
  
  /* book 2 描述 */
  Book2.title = "Python 教程"
  Book2.author = "www.runoob.com"
  Book2.subject = "Python 语言教程"
  Book2.book_id = 6495700
  
  /* 打印 Book1 信息 */
  fmt.Printf( "Book 1 title : %s\n", Book1.title)
  fmt.Printf( "Book 1 author : %s\n", Book1.author)
  fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
  fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)
  /*
  Book 1 title : Go 语言
  Book 1 author : www.runoob.com
  Book 1 subject : Go 语言教程
  Book 1 book_id : 6495407
  */
  /* 打印 Book2 信息 */
  fmt.Printf( "Book 2 title : %s\n", Book2.title)
  fmt.Printf( "Book 2 author : %s\n", Book2.author)
  fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
  fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
  /*
  Book 2 title : Python 教程
  Book 2 author : www.runoob.com
  Book 2 subject : Python 语言教程
  Book 2 book_id : 6495700
  */
}
```

### 3.结构体作为函数参数
```go
type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* 声明 Book1 为 Books 类型 */
   var Book2 Books        /* 声明 Book2 为 Books 类型 */

   /* book 1 描述 */
   Book1.title = "Go 语言"
   Book1.author = "www.runoob.com"
   Book1.subject = "Go 语言教程"
   Book1.book_id = 6495407

   /* book 2 描述 */
   Book2.title = "Python 教程"
   Book2.author = "www.runoob.com"
   Book2.subject = "Python 语言教程"
   Book2.book_id = 6495700

   /* 打印 Book1 信息 */
   printBook(Book1)
  /*
    Book title : Go 语言
    Book author : www.runoob.com
    Book subject : Go 语言教程
    Book book_id : 6495407
  */
  
   /* 打印 Book2 信息 */
   printBook(Book2)
   /*
    Book title : Python 教程
    Book author : www.runoob.com
    Book subject : Python 语言教程
    Book book_id : 6495700
   */
}

func printBook( book Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}
```

### 4.结构体指针
```go
type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* Declare Book1 of type Book */
   var Book2 Books        /* Declare Book2 of type Book */

   /* book 1 描述 */
   Book1.title = "Go 语言"
   Book1.author = "www.runoob.com"
   Book1.subject = "Go 语言教程"
   Book1.book_id = 6495407

   /* book 2 描述 */
   Book2.title = "Python 教程"
   Book2.author = "www.runoob.com"
   Book2.subject = "Python 语言教程"
   Book2.book_id = 6495700

   /* 打印 Book1 信息 */
   printBook(&Book1)

   /* 打印 Book2 信息 */
   printBook(&Book2)
}
func printBook( book *Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}
```

## 十：切片(Slice)：动态数组
语言切片是对数组的抽象
### 1.定义切片
```go
// 声明一个未指定大小的数组来定义切片
var identifier []type

// make()函数来创建切片，len 是数组的长度并且也是切片的 初始长度
var slice1 []type = make([]type, len)
// 简写为
slice1 := make([]type, len)
// 指定容量 capacity为可选参数
make([]T, length, capacity)
```

示例：
```go
a := make([]int, 0)
b := make([]int, 1)
for i := 0; i < 10; i++ {
  a = append(a, i)
  b = append(b, i)
}
fmt.Println(a)
fmt.Println(b)
/*
结果
[0 1 2 3 4 5 6 7 8 9]
[0 0 1 2 3 4 5 6 7 8 9]
*/
```

### 2.切片初始化
 - 初始化切片, []表示是切片类型，{1,2,3}初始化值依次是1,2,3.其cap=len=3
```go
  var a = []int{1, 2, 3, 4, 5, 6, 7, 8}
```

### 3.len() 和 cap() 函数
 len() 方法获取长度
  cap() 可以测量切片最长可以达到多少
 ### 4.空(nil)切片
```go
var numbers []int
if(numbers == nil){
  fmt.Printf("切片是空的")
}
/* 切片是空的 */
```
 
### 5.切片截取
 - b := a[:] 初始化切片 b, 是数组 a 的引用
```go
b := a[:]
fmt.Println("切片b是数组a的引用", b)
/* 切片b是数组a的引用 [1 2 3 4 5 6 7 8] */
```
- c := a[startIndex:endIndex] 将 a 中从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片
```go
c := a[2:6]
fmt.Println("切片c从a切片中取值", c)
/* 切片c从b切片中取值 [3 4 5 6] */
```
- d := a[startIndex:] 从startindex开始到 a 切片的最后一个元素
```go
d := a[3:]
fmt.Println(d)
/* [4 5 6 7 8] */
```
-  e := a[:endIndex] 从 a 切片开始到 endindex 元素结束
```go
d := a[:5]
fmt.Println(d)
/* [1 2 3 4 5] */
```

### 6.append() 和 copy() 函数
append
```go
var a = []int{}

// 追加一个元素
a = append(a, 1)
fmt.Println(a)

// 追加多个元素
a = append(a, 2, 3, 4)
fmt.Println(a)
/* 结果：
[1]
[1 2 3 4]
*/
```

copy：必须指定切片长度
 ```go
var a = []int{1, 2, 3, 4, 5}
var b = make([]int, len(a), cap(a))
var c = make([]int, len(a))
var d []int // 无效

copy(b, a)
copy(c, a)
copy(d, a)

fmt.Println(a, b, c, d)
/*结果：
 [1 2 3 4 5]   [1 2 3 4 5]   [1 2 3 4 5]    []
*/
 ```
 
## 十一：Map(集合)
Map 是一种无序的键值对的集合
声明：初始化使用 make 或 {} 否则无法存储数据 （nil map 不能用来存放键值对）
```go
/* 声明变量，默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
```
初始化 make {}
```go
/* 先声明后make */
var map = map[key]value
map = make(map[key][value])

/* 直接使用 make 函数 */
var map = make(map[key]value)

/* 使用 {} */
var map = map[key]value{}
```

### 1.访问单个元素，for range 循环
```go
// 初始化
var data = map[string]string{}
// 赋值
data["one"] = "第一个元素"
data["two"] = "第二个元素"
data["three"] = "第三个元素"

// 访问某个元素
fmt.Println(data["one"])
// 结果：第一个元素

// 循环输出
for key, value := range data {
  fmt.Println(key, "=>", value)
}
/* 结果
one => 第一个元素
two => 第二个元素
three => 第三个元素
*/
```

### 2.判断key是否存在
```go
// 第一种
value, ok := map[key]
fmt.Println(ok) // ok 是一个bool值 true | false
if (ok) {
  fmt.Println(value)
}
// 第二种
if _, ok := map[key]; ok {
    //存在
}
```

### 3.delete() 函数
delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key
```go
// 初始化
var data = map[string]string{}
// 赋值
data["one"] = "第一个元素"
data["two"] = "第二个元素"
data["three"] = "第三个元素"

delete(data, "one")
fmt.Println(data)
/*
map[two:第二个元素 three:第三个元素]
*/
```

## 十二：递归函数
递归，就是在运行的过程中调用自己
语法格式：
```go
func recursion() {
   recursion() /* 函数调用自身 */
}
func main() {
   recursion()
}
```

## 十三：类型转换
该资源转载自：[https://studygolang.com/articles/13139](https://studygolang.com/articles/13139)
```go
#string到int
int,err:=strconv.Atoi(string)
#string到int64
int64, err := strconv.ParseInt(string, 10, 64)
#int到string
string:=strconv.Itoa(int)
#int64到string
string:=strconv.FormatInt(int64,10)

#int到int64,把int先转成字符串再转成int64，返回带err参数的需要忽略掉
s := strconv.Itoa(int)
s64,_ := strconv.ParseInt(s,10,64)

=======================
复数，求平方，10的5次方
cmplx.Pow(10,5)
https://gowalker.org/math/cmplx#Pow
cmplx.Pow() complex 转成int64
取实数部分，float64类型的
p := real(cmplx.Pow(10,5))
float64 转成转成int64
p := int64(real(cmplx.Pow(10,5)))
------------------

float64 转成转成int64
var x float64 = 5.7
var y int = int64(x)

var value1 complex64 = 3.2 + 12i
value2 ：= 3.2 + 12i
value3 := complex(3.2, 12)
r = real(value1) //获得复数的实部
i = imag(value1) //获得复数的虚部
=======================
1、整形到字符串：
[plain] view plain copy
var i int = 1 
var s string
s = strconv.Itoa(i) 或者 s = FormatInt(int64(i), 10)

2、字符串到整形
var s string = "1" 
var i int 
i, err = strconv.Atoi(s) 或者 i, err = ParseInt(s, 10, 0)

3、字符串到float(32 / 64)
var s string = 1 
var f float32 
f, err = ParseFloat(s, 32)

float 64的时候将上面函数中的32转为64即可

4、整形到float或者float到整形
直接使用float(i) 或者 int(f) 直接进行转换即可

=======================
golang int转换成string方法：
var i int = 10
// 通过Itoa方法转换
str1 := strconv.Itoa(i)
// 通过Sprintf方法转换
str2 := fmt.Sprintf("%d", i)
=======================
(1)int转string
s := strconv.Itoa(i)
等价于s := strconv.FormatInt(int64(i), 10)

(2)int64转string
i := int64(123)
s := strconv.FormatInt(i, 10)
第二个参数为基数，可选2~36
注：对于无符号整形，可以使用FormatUint(i uint64, base int)

(3)string转int
i, err := strconv.Atoi(s)

(4)string转int64
i, err := strconv.ParseInt(s, 10, 64)
第二个参数为基数（2~36），第三个参数位大小表示期望转换的结果类型，其值可以为0, 8, 16, 32和64，分别对应 int, int8, int16, int32和int64

(5)float相关

float转string：
v := 3.1415926535
s1 := strconv.FormatFloat(v, 'E', -1, 32)//float32s2 := strconv.FormatFloat(v, 'E', -1, 64)//float64
函数原型及参数含义具体可查看：https://golang.org/pkg/strconv/#FormatFloat

string转float：

s := "3.1415926535"
v1, err := strconv.ParseFloat(v, 32)
v2, err := strconv.ParseFloat(v, 64)
PS：go语言string、int、int64互相转换


//string到int 
int,err:=strconv.Atoi(string) 
//string到int64 
int64, err := strconv.ParseInt(string, 10, 64) 
//int到string 
string:=strconv.Itoa(int) 
//int64到string 
string:=strconv.FormatInt(int64,10)
//string到float32(float64)
float,err := strconv.ParseFloat(string,32/64)
//float到string
string := strconv.FormatFloat(float32, 'E', -1, 32)
string := strconv.FormatFloat(float64, 'E', -1, 64)
// 'b' (-ddddp±ddd，二进制指数)
// 'e' (-d.dddde±dd，十进制指数)
// 'E' (-d.ddddE±dd，十进制指数)
// 'f' (-ddd.dddd，没有指数)
// 'g' ('e':大指数，'f':其它情况)
// 'G' ('E':大指数，'f':其它情况)
```

---

## 十四：接口
Go 语言提供了另外一种数据类型即接口，它把所有的具有共性的方法定义在一起，任何其他类型只要实现了这些方法就是实现了这个接口
```go
/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}
```
示例：
```go
package main

import (
    "fmt"
)

type Phone interface {
    call()
}

type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    var phone Phone

    phone = new(NokiaPhone)
    phone.call()

    phone = new(IPhone)
    phone.call()

}
```
